package com.dyna.demo.excel.handler;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;
import java.util.Objects;

/**
 * 按列分别合并处理器：对于指定列，若当前行与上一行某列内容相同，则合并该列
 */
@Slf4j
public class ExcelMergeHandler implements CellWriteHandler {
    // 要合并的列索引数组（例如 new int[]{0, 1, ..., 10}）
    private final int[] mergeColumnIndex;
    // 合并开始的行索引（通常为 1，跳过标题行）
    private final int mergeRowIndex;

    public ExcelMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
        // 不需要实现
    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 不需要实现
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        int curRowIndex = cell.getRowIndex();
        int curColIndex = cell.getColumnIndex();

        Sheet sheet = writeSheetHolder.getSheet();

        // 只在最后一列触发合并逻辑，避免重复执行
        if (curRowIndex <= mergeRowIndex || curColIndex != mergeColumnIndex[mergeColumnIndex.length - 1]) {
            return;
        }

        for (int col : mergeColumnIndex) {
            Cell currentCell = cell.getRow().getCell(col);
            Cell previousCell = sheet.getRow(curRowIndex - 1).getCell(col);

            Object currentVal = getCellValue(currentCell);
            Object previousVal = getCellValue(previousCell);

            if (Objects.equals(currentVal, previousVal)) {
                // 单列合并：只合并当前这一列
                CellRangeAddress region = new CellRangeAddress(
                        curRowIndex - 1, // startRow
                        curRowIndex,     // endRow
                        col,             // startCol == endCol == 当前列
                        col              // endCol
                );
                sheet.addMergedRegionUnsafe(region);

                // 应用居中样式到合并区域
                CellStyle sourceStyle = previousCell.getCellStyle();
                CellStyle centeredStyle = sheet.getWorkbook().createCellStyle();
                centeredStyle.cloneStyleFrom(sourceStyle);

                // 手动设置更多样式属性以确保一致性
                centeredStyle.setAlignment(HorizontalAlignment.CENTER);
                centeredStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                centeredStyle.setBorderTop(BorderStyle.THIN);
                centeredStyle.setBorderBottom(BorderStyle.THIN);
                centeredStyle.setBorderLeft(BorderStyle.THIN);
                centeredStyle.setBorderRight(BorderStyle.THIN);

                for (int r = region.getFirstRow(); r <= region.getLastRow(); r++) {
                    Row row = sheet.getRow(r);
                    Cell targetCell = row.getCell(col);
                    targetCell.setCellStyle(centeredStyle);
                }
            }
        }
    }

    /**
     * 获取单元格值（兼容不同类型）
     */
    private Object getCellValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return cell.getNumericCellValue();
            case BOOLEAN:
                return cell.getBooleanCellValue();
            case FORMULA:
                return cell.getCellFormula();
            default:
                return "";
        }
    }
}